<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Visualization Control: FilterDataTableControl - Institute for Systems Biology Visualizations</title>

    <script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
    <link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">

    <!--[if IE]><link rel="stylesheet" type="text/css" href="/css/iehacks.css" /><![endif]-->

    <script src="http://www.google.com/jsapi"></script>
    <script type="text/javascript" src="http://systemsbiology-visualizations.googlecode.com/svn/branches/1.0.1/src/main/js/load.js"></script>
</head>

<body class="gc-documentation">

<div id="gc-container">
<a name="top"></a>

<div id="codesiteContent">

<a name="gc-topnav-anchor"></a>

<div id="gc-topnav">
    <h1>Visualization Control: FilterDataTableControl</h1>

    <ul id="docs" class="gc-topnav-tabs">

        <li id="home_link">
            <a href="http://systemsbiology.org/" title="Institute for Systems Biology">Home</a>
        </li>

        <li id="docs_link">
            <a href="http://groups.google.com/group/systemsbiology-visualizations/web/visualizations-summary" class="selected"
               title="Systems Biology Visualizations Documentation">Docs</a>
        </li>

        <li id="code_link">
            <a href="http://code.google.com/p/systemsbiology-visualizations/" title="Code Repository In Google Code">Code</a>
        </li>

        <li>
            <a href="http://groups.google.com/group/systemsbiology-visualizations" title="Systems Biology Visualization Group">Group</a>
        </li>
    </ul>
</div>
<div class="g-section g-tpl-170">

<div id="gc-pagecontent">

<div class="toc">
    <ol>
        <li><a href="#Overview">Overview</a>
        <li><a href="#Example">Example</a>
        <li><a href="#Loading">Loading</a>
        <li><a href="#Data_Format">Data Format</a>
        <li><a href="#Configuration_Options">Configuration Options</a>
        <li><a href="#Methods">Methods</a>
        <li><a href="#Events">Events</a>
        <li><a href="#Data_Policy">Data Policy</a>
    </ol>
</div>

<h1><a name="Overview" id="Overview"></a>Overview</h1>

<p>
The <code>FilterDataTableControl</code> is a Visualization that acts as a control over other visualizations.  It is rendered within the browser using HTML.
This visualization offers the ability to select some criteria to filter the <code>DataTable</code> used by the controlled visualizations.
Any visualization may be registered with this control, and it fully supports <code>"select"</code> event propagation.

<p>By default the <code>FilterDataTableControl</code> offers a set of simple controls over <code>"string"</code>, <code>"number"</code> and <code>"boolean"</code> columns (I refer to these as <code>FilterColumnControls</code>).

<p>
The <code>FilterDataTableControl</code> does not provide the ability to filter "date", "datetime" or "timeofday" columns.  However it exposes
an interface to allow developers to register their own custom <code>FilterColumnControls</code>.  You can read our documentation for
<a href="CustomizedFilterColumnControl.html">Customizing Filter Column Controls</a>.

<p>
    By: Hector Rovira for the Institute for Systems Biology (ISB)<br/>
    <strong>This work was made possible by funding from "The Systems Approach to Immunity and Inflammation Contract" (HHSN272200700038C) from the National Institute of Allergy and Infectious Diseases (NIAID)</strong>
</p>

<h2>Filter Data Table Control Lifecycle</h2>
When new filter criteria is selected:
<ol>
    <li>A <strong>filtered</strong> <code>DataTable</code> is created</li>
    <li>The <strong>original</strong> <code>DataTable</code> is read and every row is evaluated against all active <code>FilterColumnControls</code></li>
    <li>Each row that passes the filter criteria is copied over to the <strong>filtered</strong> <code>DataTable</code> depending on one of these options
        <ul>
            <li><strong>All Must Pass</strong> - this rule ensures that a row must pass the criteria for all active <code>FilterColumnControls</code></li>
            <li><strong>At Least One Must Pass</strong> - this rule ensures that a row must pass the criteria for at least one of the active <code>FilterColumnControls</code></li>
        </ul>
    </li>
    <li>Selection mappings are maintained between the <strong>original</strong> and <strong>filtered</strong> <code>DataTables</code> (to support select event propagation with non-controlled visualizations)</li>
    <li>Finally, the <strong>filtered</strong> <code>DataTable</code> is propagated to the registered visualizations</li>
</ol>

<h2>Default Column Filter Controls</h2>
<table>
    <tr>
        <th>Data Type</th>
        <th>Control Type</th>
        <th>Visualization</th>
        <th>Filter Criteria</th>
    </tr>
    <tr>
        <td><code>string</code></td>
        <td>Multiple Select Drop-Down</td>
        <td>Compiles a list of distinct values in the controlled column and visualizes it as a multiple select box</td>
        <td>The value from the controlled column must match one of the selected values</td>
    </tr>
    <tr>
        <td><code>number</code></td>
        <td>Single Select Drop-Down<br/>and Input Text Field</td>
        <td>Displays a selection of simple mathematical comparison operators (Greater Than, Less Than, Equals, etc) and an input text field to capture the value to compare against</td>
        <td>The value from the controlled column must pass the criteria expressed by the operation in the control</td>
    </tr>
    <tr>
        <td><code>boolean</code></td>
        <td>Radio Buttons</td>
        <td>Offers a true or false choice for the controlled column</td>
        <td>The value from the controlled column must match the selected choice</td>
    </tr>
</table>

<h1><a name="Example" id="Example"></a>Example</h1>
<style type="text/css">
    div#container {
        margin: 0 auto;
        padding: 2px;
        background: #FFF
    }

    div#containerFilterControl {
        border: 1px solid gray;
    }

    table#visualizationsContainer {
        padding: 3px;
        margin: 1em auto;
        width: 90%;
        border: 1px solid gray;
    }

    h2 {
        font: lighter 150% "Trebuchet MS", Arial sans-serif;
        color: #9E4A24
    }
</style>

<div id="container">
    <div id="containerFilterControl">
    </div>

    <table id="visualizationsContainer" border="0" cellpadding="0" cellspacing="10">
        <tr>
            <td width="50%" align="center">
                <h2><span>Table A: Unfiltered</span></h2>

                <div id="table_a_container">
                </div>
            </td>
            <td width="50%" align="center">
                <h2><span>Table B: Filtered</span></h2>

                <div id="table_b_container">
                </div>
            </td>
        </tr>
        <tr>
            <td width="50%" align="center">
                <h2><span>Table C: Filtered</span></h2>

                <div id="table_c_container">
                </div>
            </td>
            <td width="50%" align="center">
                <h2><span>Line Chart: Filtered</span></h2>

                <div id="line_chart_container">
                </div>
            </td>
        </tr>
    </table>
</div>

<script type="text/javascript">
    google.load("prototype", "1.6.0.2");
    google.load("scriptaculous", "1.8.1");
    google.load("visualization", "1", {packages:["table", "linechart"]});
</script>
<script type="text/javascript">
    systemsbiology.load("visualization", "1.0.1", {packages:["filterDataTableControl"]});

    function drawVisualizations() {
        var data = new google.visualization.DataTable();
        data.addColumn("string", "Name");
        data.addColumn("number", "Height");
        data.addColumn("number", "Age");
        data.addColumn("boolean", "Girl?");
        data.addRows(4);
        data.setCell(0, 0, "Hector");
        data.setCell(0, 1, 67);
        data.setCell(0, 2, 33);
        data.setCell(0, 3, false);
        data.setCell(1, 0, "Isola");
        data.setCell(1, 1, 30);
        data.setCell(1, 2, 3);
        data.setCell(1, 3, true);
        data.setCell(2, 0, "Mindy");
        data.setCell(2, 1, 64);
        data.setCell(2, 2, 33);
        data.setCell(2, 3, true);
        data.setCell(3, 0, "Jacek");
        data.setCell(3, 1, 25);
        data.setCell(3, 2, 1);
        data.setCell(3, 3, false);

        var tableA = new google.visualization.Table($("table_a_container"));
        var tableB = new google.visualization.Table($("table_b_container"));
        var tableC = new google.visualization.Table($("table_c_container"));
        var linechart = new google.visualization.LineChart($("line_chart_container"));
        var filterControl = new org.systemsbiology.visualization.FilterDataTableControl($("containerFilterControl"));
        filterControl.draw(data, {
            controlledVisualizations: [
            {visualization: tableB, options: {showRowNumber:true}},
            {visualization: tableC, options: {showRowNumber:false, sort: "disable"}},
            {visualization: linechart, options: {width: 400, height: 240, legend: "bottom", title: "Family Stats"}}
                    ],
            columnIndexesToFilter: [0,2,3],
            columnFilterControlConfigByColumnIndex: {
                column_3: { labelForTrue:"Girl", labelForFalse:"Boy"}
            },
            simpleOperatorLabels: {
                gt: "Greater Than",
                ge: "Greater Or Equal To",
                eq: "Equals",
                ne: "Does Not Equal",
                lt: "Less Than",
                le: "Less Than Or Equal To"
            }
        });

        tableA.draw(data,{showRowNumber:false});

            // add listeners
        google.visualization.events.addListener(tableA, "select", function() {
            filterControl.setSelection(tableA.getSelection());
        });
        google.visualization.events.addListener(filterControl, "select", function() {
            tableA.setSelection(filterControl.getSelection());
        });
        google.visualization.events.addListener(tableB, "select", function() {
            tableC.setSelection(tableB.getSelection());
        });
        google.visualization.events.addListener(tableC, "select", function() {
            tableB.setSelection(tableC.getSelection());
        });
    }

    google.setOnLoadCallback(drawVisualizations);
</script>

<pre class="prettyprint">
&lt;html&gt;
&lt;head&gt;
&lt;script type="text/javascript" src="http://www.google.com/jsapi"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
    google.load("prototype", "1.6.0.2");
    google.load("scriptaculous", "1.8.1");
    google.load("visualization", "1", {packages:["table", "linechart"]});
&lt;/script&gt;
&lt;script type="text/javascript" src="http://systemsbiology-visualizations.googlecode.com/svn/branches/1.0.1/src/main/js/load.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
    systemsbiology.load("visualization", "1.0.1", {packages:["filterDataTableControl"]});
&lt;/script&gt;

&lt;script type="text/javascript"&gt;
    function drawVisualizations() {
        var data = new google.visualization.DataTable();
        data.addColumn("string", "Name");
        data.addColumn("number", "Height");
        data.addColumn("number", "Age");
        data.addColumn("boolean", "Girl?");
        data.addRows(4);
        data.setCell(0, 0, "Hector");
        data.setCell(0, 1, 67);
        data.setCell(0, 2, 33);
        data.setCell(0, 3, false);
        data.setCell(1, 0, "Isola");
        data.setCell(1, 1, 30);
        data.setCell(1, 2, 3);
        data.setCell(1, 3, true);
        data.setCell(2, 0, "Mindy");
        data.setCell(2, 1, 64);
        data.setCell(2, 2, 33);
        data.setCell(2, 3, true);
        data.setCell(3, 0, "Jacek");
        data.setCell(3, 1, 25);
        data.setCell(3, 2, 1);
        data.setCell(3, 3, false);

        var tableA = new google.visualization.Table($("table_a_container"));
        var tableB = new google.visualization.Table($("table_b_container"));
        var tableC = new google.visualization.Table($("table_c_container"));
        var linechart = new google.visualization.LineChart($("line_chart_container"));
        var filterControl = new org.systemsbiology.visualization.FilterDataTableControl($("containerFilterControl"));
        filterControl.draw(data, {
            controlledVisualizations: [
            {visualization: tableB, options: {showRowNumber:true}},
            {visualization: tableC, options: {showRowNumber:false, sort: "disable"}},
            {visualization: linechart, options: {width: 400, height: 240, legend: "bottom", title: "Family Stats"}}
                    ],
            columnIndexesToFilter: [0,1,3],
            columnFilterControlConfigByColumnIndex: {
                column_3: { labelForTrue:"Girl", labelForFalse:"Boy"}
            }
            simpleOperatorLabels: {
                gt: "Greater Than",
                ge: "Greater Or Equal To",
                eq: "Equals",
                ne: "Does Not Equal",
                lt: "Less Than",
                le: "Less Than Or Equal To"
            }
        });

        tableA.draw(data,{showRowNumber:false});

        // add listeners
        google.visualization.events.addListener(tableA, "select", function() {
            filterControl.setSelection(tableA.getSelection());
        });
        google.visualization.events.addListener(filterControl, "select", function() {
            tableA.setSelection(filterControl.getSelection());
        });
        google.visualization.events.addListener(tableB, "select", function() {
            tableC.setSelection(tableB.getSelection());
        });
        google.visualization.events.addListener(tableC, "select", function() {
            tableB.setSelection(tableC.getSelection());
        });
    }

    google.setOnLoadCallback(drawVisualizations);
&lt;/script&gt;
&lt;style type="text/css"&gt;
    div#container {
        margin: 0 auto;
        padding: 2px;
        background: #FFF
    }

    div#containerFilterControl {
        border: 1px solid gray;
    }

    table#visualizationsContainer {
        padding: 3px;
        margin: 1em auto;
        width: 90%;
        border: 1px solid gray;
    }

    h2 {
        font: lighter 150% "Trebuchet MS", Arial sans-serif;
        color: #9E4A24
    }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="container"&gt;
    &lt;div id="containerFilterControl"&gt;
    &lt;/div&gt;

    &lt;table id="visualizationsContainer" border="0" cellpadding="0" cellspacing="10"&gt;
        &lt;tr&gt;
            &lt;td width="50%" align="center"&gt;
                &lt;h2&gt;&lt;span&gt;Table A: Unfiltered&lt;/span&gt;&lt;/h2&gt;

                &lt;div id="table_a_container"&gt;
                &lt;/div&gt;
            &lt;/td&gt;
            &lt;td width="50%" align="center"&gt;
                &lt;h2&gt;&lt;span&gt;Table B: Filtered&lt;/span&gt;&lt;/h2&gt;

                &lt;div id="table_b_container"&gt;
                &lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td width="50%" align="center"&gt;
                &lt;h2&gt;&lt;span&gt;Table C: Filtered&lt;/span&gt;&lt;/h2&gt;

                &lt;div id="table_c_container"&gt;
                &lt;/div&gt;
            &lt;/td&gt;
            &lt;td width="50%" align="center"&gt;
                &lt;h2&gt;&lt;span&gt;Line Chart: Filtered&lt;/span&gt;&lt;/h2&gt;

                &lt;div id="line_chart_container"&gt;
                &lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>

<h1><a name="Loading" id="Loading"></a>Loading</h1>

<p>
   The <code>systemsbiology.load</code> package name is <code>"filterDataTableControl"</code>
</p>

<pre class="prettyprint">&lt;script type="text/javascript" src="http://systemsbiology-visualizations.googlecode.com/svn/branches/1.0.1/src/main/js/load.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
    systemsbiology.load("visualization", "1.0.1", {packages:["filterDataTableControl"]});
&lt;/script&gt;</pre>

<p>
    The visualization control's class name is <code>org.systemsbiology.visualization.FilterDataTableControl</code>
</p>

<pre class="prettyprint">var filterControl = new org.systemsbiology.visualization.FilterDataTableControl(container);</pre>

<p/>

<h1><a name="Data_Format" id="Data_Format"></a>Data Format</h1>

<p>
    This visualization supports all data formats.
</p>

<h1><a name="Configuration_Options" id="Configuration_Options"></a>Configuration Options</h1>

<p>
<table>
    <tr>
        <th>Name</th>
        <th>Type</th>
        <th>Default</th>
        <th>Description</th>
    </tr>
    <tr>
        <td>columnIndexesToFilter</td>
        <td>Array</td>
        <td>all columns</td>
        <td>An array of column indexes corresponding to the <strong>original</strong> <code>DataTable</code>, indicating the columns that should be filtered.  For example:
<pre class="prettyprint">columnIndexesToFilter: [0,1,3]</pre>
        </td>
    </tr>
    <tr>
        <td>columnFilterControlConfigByColumnIndex</td>
        <td>Array</td>
        <td>empty</td>
        <td>Filter configuration options that can override the visualization of each column's filter.  For example:
<pre class="prettyprint">columnFilterControlConfigByColumnIndex: {
    column_3: { labelForTrue:"Girl", labelForFalse:"Boy"}
}</pre>
        </td>
    </tr>
    <tr>
        <td>controlledEvent</td>
        <td>string</td>
        <td><code>"filtered-select"</code></td>
        <td>A label for the event to be published to the controlled visualizations</td>
    </tr>
    <tr>
        <td>controlledVisualizations</td>
        <td>Array</td>
        <td>empty</td>
        <td>A list of visualizations and their options.  For example:
<pre class="prettyprint">controlledVisualizations: [
    {visualization: table2, options: {showRowNumber:true}},
    {visualization: linechart5, options: {legend: "bottom", title: "Family Stats"}}
]</pre></tr>
    <tr>
        <td>hideFilterContainerOnOpen</td>
        <td>boolean</td>
        <td><code>false</code></td>
        <td>Configures the start view of the control.  Collapsed if set to <code>true</code>.</td>
    </tr>
    <tr>
        <td>labelForAnd</td>
        <td>string</td>
        <td><code>"All Must Pass"</code></td>
        <td>Label to show in the control for the "AND" case</td>
    </tr>
    <tr>
        <td>labelForOr</td>
        <td>string</td>
        <td><code>"At Least One Must Pass"</code></td>
        <td>Label to show in the control for the "OR" case</td>
    </tr>
    <tr>
        <td>labelForTitle</td>
        <td>string</td>
        <td><code>"Filters"</code></td>
        <td>Title Label open and closes the control</td>
    </tr>
    <tr>
        <td>simpleOperatorLabels</td>
        <td>Object</td>
        <td>simple labels</td>
        <td>Labels for the operators in the numeric filter select box.  For example:
<pre class="prettyprint">
simpleOperatorLabels: {
    gt: "Greater Than", ge: "Greater Or Equal To",
    eq: "Equals", ne: "Does Not Equal",
    lt: "Less Than", le: "Less Than Or Equal To"
}</pre>
        </td>
    </tr>
</table>

<h2>Configuration Options for Default FilterColumnControls</h2>
All <code>FilterColumnControls</code> receive an options Object on the draw method, containing these properties:
<ul>
    <li>assignedColumnIndex: column index assigned to the control</li>
    <li>inheritedOptions: options passed to the <code>FilterDataTableControl</code></li>
</ul>
These tables show the configuration for each of the default <code>FilterColumnControls</code> provided:
<h3>SelectDistinctValuesStringFilterColumnControl</h3>
<table>
    <tr>
        <th>Name</th>
        <th>Type</th>
        <th>Default</th>
        <th>Description</th>
    </tr>
    <tr>
        <td>assignedColumnIndex</td>
        <td>number</td>
        <td>none</td>
        <td>Assigned by the <code>FilterDataTableControl</code> during draw method</td>
    </tr>
</table>
<h3>SimpleOperatorNumberFilterColumnControl</h3>
<table>
    <tr>
        <th>Name</th>
        <th>Type</th>
        <th>Default</th>
        <th>Description</th>
    </tr>
    <tr>
        <td>assignedColumnIndex</td>
        <td>number</td>
        <td>none</td>
        <td>Assigned by the <code>FilterDataTableControl</code> during draw method</td>
    </tr>
    <tr>
        <td>simpleOperatorLabels</td>
        <td>Object</td>
        <td>simple labels</td>
        <td>Labels for the operators in the numeric filter select box.  For example:
<pre class="prettyprint">
simpleOperatorLabels: {
    gt: "Greater Than", ge: "Greater Or Equal To",
    eq: "Equals", ne: "Does Not Equal",
    lt: "Less Than", le: "Less Than Or Equal To"
}</pre>
        </td>
    </tr>
</table>
<h3>SimpleChoiceBooleanFilterColumnControl</h3>
<table>
    <tr>
        <th>Name</th>
        <th>Type</th>
        <th>Default</th>
        <th>Description</th>
    </tr>
    <tr>
        <td>assignedColumnIndex</td>
        <td>number</td>
        <td>none</td>
        <td>Assigned by the <code>FilterDataTableControl</code> during draw method</td>
    </tr>    
    <tr>
        <td>columnFilterControlConfigByColumnIndex</td>
        <td>Object</td>
        <td>simple true/false labels</td>
        <td>Accessed from the <code>columnFilterControlConfigByColumnIndex</code> option by <code>assignedColumnIndex</code>.
            <br/>Provides labels for the radio buttons.  For example:
<pre class="prettyprint">columnFilterControlConfigByColumnIndex: {
    column_3: { labelForTrue: "Girl", labelForFalse: "Boy" }
}</pre>
        </td>
    </tr>
</table>

<h1><a name="Methods" id="Methods"></a>Methods</h1>

<p>
<table>
    <tr>
        <th>Method</th>
        <th>Return Type</th>
        <th>Description</th>
    </tr>
    <tr>
        <td><code>draw(data, options)</code></td>
        <td>none</td>
        <td>Draws the control and its controlled visualizations</td>
    </tr>
    <tr>
        <td><code>applyFilter()</code></td>
        <td>none</td>
        <td>Called from the visualization to apply the newly selected filters.  Can be called by another object that is modifying the data.</td>
    </tr>
    <tr>
        <td><code>resetFilter()</code></td>
        <td>none</td>
        <td>Propagates to its controlled visualizations the <strong>original</strong> <code>DataTable</code> without any filters.</td>
    </tr>
    <tr>
        <td><code>getSelection()</code></td>
        <td>Array of selection elements</td>
        <td>Selection elements are all row elements of the <strong>original</strong> <code>DataTable</code>, mapped from the <strong>filtered</strong> <code>DataTable</code>. Can return more than one selected row.</td>
    </tr>
    <tr>
        <td><code>setSelection(selection)</code></td>
        <td>none</td>
        <td>Treats every selection entry as a row selection. Supports selection of mutiple rows.  Maps the selection to the filteredData and publishes a <code>"filtered-select"</code> event to the controlled visualizations.</td>
    </tr>
</table>

<h1><a name="Events" id="Events"></a>Events</h1>

<p>
<table>
    <tr>
        <th>Name</th>
        <th>Description</th>
        <th>Properties</th>
    </tr>
    <tr>
        <td>select</td>
        <td>Standard select event</td>
        <td>None</td>
    </tr>
    <tr>
        <td>filtered-select</td>
        <td>Published to controlled visualizations upon receipt of an external select event.</td>
        <td>None</td>
    </tr>
</table>

<p>
Note on Event Propagation:
<ul>This control extends <code>org.systemsbiology.visualization.MappedSelectEventPropagation</code>, receiving the following functionality:
    <li>Listens to controlled visualization <code>"select"</code> events (if any), maps them to <strong>original</strong> <code>DataTable</code> selections, and publishes its own <code>"select"</code> event</li>
    <li>On a call to <code>"setSelection"</code>, this control will map the given selection object to <strong>filtered</strong> <code>DataTable</code> selections, and publish a <code>"filtered-select"</code> event to any controlled visualizations that implement <code>"setSelection"</code></li>
</ul>

<h1><a name="Data_Policy" id="Data_Policy"></a>Data Policy</h1>
<p>
    All code and data are processed and rendered in the browser. No data is sent to any server.
</p>

</div>
</div>

</div>

<div id="gc-footer" dir="ltr">
    <div id="gc-footer-img"></div>
    <div class="text">

        &copy;2008 Institute for Systems Biology -
        <a href="http://www.systemsbiology.org">ISB Home</a> -
        <a href="http://code.google.com/p/systemsbiology-visualizations/">Code Home</a>
    </div>
</div>
<!-- end gc-footer -->

</div>
<!-- end gc-containter -->
</body>
</html>

